iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
1
Modern Web

三十天路邊賭場上線了!系列 第 18

DAY18 狀態管理初始化、籌碼金額使用Redux

  • 分享至 

  • xImage
  •  

前言

昨天我們造了一個簡易版本Redux,當然有很多其他Redux方便的東西,但小弟水平有限、並沒有特別使用其他部分,畢竟學的穩才能走得久,沒有特別學一手工具,未來慢慢增加囉!考量到其實用到的不多,其實籌碼、金額差不多就這樣,但因為我不想讓狀態非常凌亂。

預覽

結構

我們新增了一個Store資料夾,有actions、reducer、store等等,我們需要的一切。

└─src
    │  App.ts
    │  Game.ts
    ├─components
    │  ├─elements
    │  │      ...省略
    │  ├─groups
    │  │      ...省略
    │  └─objects
    │          ...省略
    ├─config
    │      ...省略
    │      
    ├─loaders
    │      ...省略
    ├─store  ***
    │      actions.ts
    │      index.ts
    │      reducer.ts
    │      redux.ts
    │      store.ts
    └─utils

actions

這是我們action部分,包含action type,有給他一些基礎類型,讓我們派發的時候順順利利,有預設類型,方便我選擇。

import chipType from '@/config/chipType'
export interface Action {
  type: string,
  payload: any
}

export interface chipPayload {
  chip: keyof typeof chipType
}

export interface balancePayload {
  balance: Number
}
/*
 * action type
 */

export const UPDATE_BALANCE = 'UPDATE_BALANCE'
export const UPDATE_CHIP = 'UPDATE_CHIP'
export const INIT = 'INIT'

/*
 * action creator
 */

export function updateBalance(payload: balancePayload) {
  return { type: UPDATE_BALANCE, payload }
}

export function updateChip(payload: chipPayload) {
  return { type: UPDATE_CHIP, payload }
}

export function init() {
  return { type: INIT }
}

reducer

這是我們的reducer,有一些我們派發動作之後會做的行為。有更新餘額以及更新選擇的籌碼。

import { UPDATE_BALANCE, UPDATE_CHIP, Action } from './actions'

function reducer(state = {}, action: Action) {
  switch (action.type) {
    case UPDATE_BALANCE:
      return Object.assign({}, state, { balance: action.payload.balance })
    case UPDATE_CHIP:
      return Object.assign({}, state, { chip: action.payload.chip })
    default:
      return state
  }
}

export default reducer

store

Store就是我們建出我們Store的地方,就可以直接引入,直接dispatch,舒舒服服的使用。

import { reducer, createStore } from "@/store/index";

let store = createStore(reducer, { chip: '1000', balance: 99999 })

export default store

籌碼區塊

我們增加hookChip,針對每一個chip綁上subscribe,只要store有更新就會通知訂閱者,訂閱者就會去與store要取新資料,並把現在選取的籌碼設定為選取狀態。至於為何要先執行一次update,其原因就是因為首次進入時,就算store有初始化,但那時訂閱者還沒訂閱store,導致畫面第一次並沒有更新,因此我們需要先取一次狀態。

ChipBox.ts

// ...引入省略

export default class ChipBox extends WrapperContainerCenter {
  private _chipList: Array<Chip> = []
 
  constructor() {
    super()
    for (let v in chipType) {
      let chip = new Chip(v as keyof typeof chipType)
      this.addChild(chip)
      this._chipList.push(chip)
    }
    for (let i in this._chipList) {
      this._chipList[i].setPosition({ animation: false }, Number(i) * this._chipList[i].width * 1.05, 0)
      this._chipList[i].setInteractive(true)
      this.hookChip(this._chipList[i])
    }
  }

  public hookChip(chip: Chip) {
    chip.setInteractive(true)
    chip.onClick(() => {
      store.dispatch(actions.updateChip({ chip: chip.value }))
    })

    let _update = () => {
      let state = store.getState()
      if (state.chip === chip.value) {
        chip.setPosition({ animation: true }, chip.x, -30)
      } else {
        chip.setPosition({ animation: true }, chip.x, 0)
      }
    }
  
    store.subscribe(_update)
    _update()
  }

  public setPosition(animationOpt: WrapperType.animationOpt, x: number, y: number): void {
    this.updateCenter()
    this._centerContainer.setPosition(animationOpt, x, y)
  }
}

餘額顯示

一樣初始化時先取得目前store資料,並更新目前餘額。

// Info.ts

// ... 省略引入

export default class Info extends WrapperContainer {
  private _infoMoneyNumber: InfoMoneyNumber
  private _infoBg: Sprite
  private _moneyIcon: Sprite
  private _balance: number

  constructor() {
    super()
    this._infoBg = new Sprite(imagePath.interfacePath, 'infobg')
    this._moneyIcon = new Sprite(imagePath.interfacePath, 'money')
    this._balance = 0
    this._infoMoneyNumber = new InfoMoneyNumber(this._balance)

    this.addChild(this._infoBg)
    this.addChild(this._moneyIcon)
    this.addChild(this._infoMoneyNumber)

    this._infoMoneyNumber.setPosition({ animation: false }, 70, 67)
    this._moneyIcon.setPosition({ animation: false }, 10, 100)
    this._moneyIcon.setRotation(false, -Math.PI * 0.5)

    let _update = () => {
      let { balance } = store.getState()
      this._infoMoneyNumber.updateNumber(balance)
    }
    store.subscribe(_update)
    _update()
  }
}

後記

今天的內容算是昨天的延伸,接下來應該就是難搞的籌碼亂飛,下注狀態等等,目前後端遊戲伺服器已經大概有雛形,等到穩定之後即可串上前端介面了!

連結

Githun
Redux中文
Redux


上一篇
DAY17 導入狀態管理、造個Redux
下一篇
DAY 19 牌局結果、結果提示
系列文
三十天路邊賭場上線了!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言